<!doctype html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<link rel="stylesheet" href="./../../assets/css/combined.css">
	<link rel="shortcut icon" href="./../../favicon.ico" />
	<script src="http://www.google.com/jsapi" type="text/javascript"></script>
	<script type="text/javascript">
		var path = './../../';
		var class_prefix = "Session::";
	</script>
	<script src="./../../assets/js/combined.js"></script>
	<title>Session Advanced - Classes - FuelPHP Documentation</title>
</head>
<body>
	<div id="container">
		<header id="header">
			<div class="table">
				<h1>
					<strong>FuelPHP, a PHP 5.3 Framework</strong>
					Documentation
				</h1>

				<form id="google_search">
					<p>
						<span id="search_clear">&nbsp;</span>
						<input type="submit" name="search_submit" id="search_submit" value="search" />
						<input type="text" value="" id="search_input" name="search_input" />
					</p>
				</form>
			</div>
			<nav>

				<div class="clear"></div>
			</nav>
			<a href="#" id="toc_handle">table of contents</a>
			<div class="clear"></div>
		</header>

		<div id="cse">
			<div id="cse_point"></div>
			<div id="cse_content"></div>
		</div>

		<div id="main">

			<h2>Session Class</h2>

			<p>The session class allows you to maintain state for your application in the stateless environment of the web.
				It allows you to store variables on the server using a variety of storage solutions, and recall these variables on the next page request.</p>

			<h3 id="manual_loading">Manual loading</h3>

			<p>
				For most cases, it is sufficient to configure the desired driver, and use the methods documented on the <a href="./usage.html">usage</a> page.
				However, there are situations where you would like more control over the way sessions behave.
				You might want to use a different session driver than is configured in the session configuration file.
				Or you have a need for multiple drivers concurrently. This is where the <kbd>forge</kbd> method comes in.
			</p>
			<p>
				The <kbd>forge</kbd> method returns an instance of the session class, using the driver defined in the configuration file or via the parameter.
				You can use the methods documented on the <a href="./usage.html">usage</a> page on the object returned, using dynamic calls.
			</p>

			<article>
				<h4 class="method" id="method_forge">forge($config = array())</h4>
				<p>
					The <strong>forge</strong> method allows you to manually instantiate a session driver.
				</p>
				<table class="method">
					<tbody>
					<tr>
						<th>Static</th>
						<td>Yes</td>
					</tr>
					<tr>
						<th>Parameters</th>
						<td>
							<table class="parameters">
								<tr>
									<th>Param</th>
									<th>Default</th>
									<th>Description</th>
								</tr>
								<tr>
									<th><kbd>$config</kbd></th>
									<td><i>optional</i></td>
									<td>
										You can select the driver of your choice by simply passing the name of the driver to the forge method.
										If you require more custom configuration, define a $config array, using the parameters documented on the <a href="./config.html">configuration</a> page.
										Configuration settings you pass here will override the ones defined in the configuration file.
									</td>
								</tr>
							</table>
						</td>
					</tr>
					<tr>
						<th>Returns</th>
						<td>object - The instantiated session object.</td>
					</tr>
					<tr>
						<th>Example</th>
						<td>
							<pre class="php"><code>// instantiate a database session
$session = Session::forge('db');

// get the counter from the session
$counter = $session->get('counter');

// if not present, set a default
if ($counter === false)
{
	$counter = 0;
}

// write the counter back
$session->set('counter', $counter);

// no need to explicitly write, Fuel will take care of that...

// you can also load a driver with settings that will override the defaults in the config file
$session = Session::forge( array('driver' => 'memcached', 'expiration_time' => 3600, 'memcached' = array('cookie_name' => 'appcookie')) );
</code></pre>
						</td>
					</tr>
					</tbody>
				</table>

				<p class="note">
					<kbd>Please note:</kbd> when you want to use multiple session drivers at the same time, the <kbd>cookie_name</kbd> for each of these driver instances must be unique.
					If you attempt to load a driver using a <kbd>cookie_name</kbd> that is already in use, and the instance using it uses the same driver as you are trying to load, that instance is reused.
					If the instance is using a different driver, an exception is thrown.
				</p>

			</article>

			<article>
				<h4 class="method" id="method_rotate">rotate()</h4>
				<p>
					The <strong>rotate</strong> method allows you to manually force a rotation of the session id. You can use this as an extra security measure, for example when the security level of the current user is modified.
				</p>
				<table class="method">
					<tbody>
					<tr>
						<th>Static</th>
						<td>No</td>
					</tr>
					<tr>
						<th>Parameters</th>
						<td>
							None
						</td>
					</tr>
					<tr>
						<th>Returns</th>
						<td>void</td>
					</tr>
					<tr>
						<th>Example</th>
						<td>
							<pre class="php"><code>// instantiate a database session
$session = Session::forge('db');

// force a rotation of the session id
$session->rotate();
</code></pre>
						</td>
					</tr>
					</tbody>
				</table>

			</article>

			<article>
				<h4 class="method" id="method_get_config">get_config()</h4>
				<p>
					The <strong>get_config</strong> method allows retrieve a session driver configuration item.
				</p>
				<table class="method">
					<tbody>
					<tr>
						<th>Static</th>
						<td>No</td>
					</tr>
					<tr>
						<th>Parameters</th>
						<td>
							<table class="parameters">
								<tr>
									<th>Param</th>
									<th>Default</th>
									<th>Description</th>
								</tr>
								<tr>
									<th><kbd>$name</kbd></th>
									<td><i>required</i></td>
									<td>
										Name of the session configuration variable.
									</td>
								</tr>
							</table>
						</td>
					</tr>
					<tr>
						<th>Returns</th>
						<td>mixed, the value requested, or null of the requested variable does not exist.</td>
					</tr>
					<tr>
						<th>Example</th>
						<td>
							<pre class="php"><code>// instantiate a database session
$session = Session::forge('db');

// get the defined session cookie name
$cookiename = $session->get_config('cookie_name');
</code></pre>
						</td>
					</tr>
					</tbody>
				</table>

			</article>

			<article>
				<h4 class="method" id="method_set_config">set_config()</h4>
				<p>
					The <strong>set_config</strong> method allows alter a session driver configuration item at runtime.
				</p>
				<table class="method">
					<tbody>
					<tr>
						<th>Static</th>
						<td>No</td>
					</tr>
					<tr>
						<th>Parameters</th>
						<td>
							<table class="parameters">
								<tr>
									<th>Param</th>
									<th>Default</th>
									<th>Description</th>
								</tr>
								<tr>
									<th><kbd>$name</kbd></th>
									<td><i>required</i></td>
									<td>
										Name of the session configuration variable.
									</td>
								</tr>
							</table>
						</td>
					</tr>
					<tr>
						<th>Returns</th>
						<td>void</td>
					</tr>
					<tr>
						<th>Example</th>
						<td>
							<pre class="php"><code>// instantiate a database session
$session = Session::forge('db');

// set the expiration time for this session  to 2 hours
$session->set_config('expiration_time', 7200);
</code></pre>
						</td>
					</tr>
					</tbody>
				</table>

			</article>

			<h2>Using sessions with Flash</h2>

			<p>
				One of the problems with using Flash objects in websites, is that when they interact with your web application, they don't send the cookies
				back that have been stored in the browser. Due to this problem, it is difficult to make them aware of the session state of the application.
			</p>

			<p>
				To solve this problem, the Session class allows you to pass the cookie to the application using a POST variable.
				You can set the name of the variable using the configuration setting 'post_cookie_name'. If the Session class finds a $_POST variable with this name,
				it will assume it contains the session cookie, and will not use the session cookie. This allows you to copy the contents of the session cookie
				client-side into the POST variable using a bit of javascript.
			</p>

			<p class="note">
				When you use a Flash based uploader. you will have to set the <kbd>match_ua</kbd> setting to <kbd>false</kbd>.
				You have to do this because Flash uses a different User Agent which will prevent the Session class to correctly
				identify the users session.
			</p>

							<pre class="javascript"><code>// function to get the session cookie
// you can use or own, or use the one your favorite javascript framework provides
function getCookie(c_name)
{
	if (document.cookie.length > 0)
	{
		c_start = document.cookie.indexOf(c_name + "=");

		if (c_start != -1)
		{
			c_start = c_start + c_name.length + 1;
			c_end = document.cookie.indexOf(";", c_start);
			if (c_end == -1) c_end = document.cookie.length;
			return unescape(document.cookie.substring(c_start, c_end));
		}
	}

	return "";
}

// we're using jquery and uploadify in this example, and we're passing
// the fuel cookie (called 'fuelcid' here) in the formData as 'fuelcid'

// Note: when generating this code, don't hardcode the cookie name, but
// instead get the cookie name from the session configuration file.

// Note:: check the "sessions without cookies" section below if you
// don't have a cookie available to pass the session id back

// ( parameters are related to Uploadify Version 3.2 )

$(function()
{
	$('#custom_file_upload').uploadify(
	{
		'swf'            : '/uploadify/uploadify.swf',
		'uploader'       : '/uploadify/uploadify.php',
		'multi'          : true,
		'auto'           : true,
		'fileTypeExts'   : '*.jpg;*.gif;*.png',
		'fileTypeDesc'   : 'Image Files (.JPG, .GIF, .PNG)',
		'queueID'        : 'custom-queue',
		'queueSizeLimit' : 3,
		'removeCompleted': false,
		'formData'       : {'fuelcid': getCookie('fuelcid')},
		'onSelect'       : function(file)
		{
			alert('The file ' + file.name + ' was added to the queue.');
		},
		'onQueueComplete' : function(queueData)
		{
			alert(queueData.uploadsSuccessful + ' files were successfully uploaded.');
		}
	});
}
</code></pre>

			<h3 id="concurrency">Concurrency</h3>

			<p>
				When talking about sessions, session cookies, and their behaviour, it is important to understand how they work
				and what the possibilities and limitations are.
			</p>
			<p>
				This is especially true when it comes to concurrency.
				For web-based application, you will have concurrency if you use multiple asynchronous ajax calls on your webpages,
				or if you allow a browser to have multiple windows open to the same application (which, lets face it, is something you can't prevent).
			</p>
			<p>
				Something else you need to know is that by default, the session class will rotate (or regenerate) the session id on a regular basis,
				to prevent session hijacking due to session id fixation (someone stealing your session cookie and use it to take over your session).
				You can control the rotation time using a configuration setting, or even disable it, but from a security point of view that is a bad idea.
				Take these two together, and you have a potential disaster on your hands!
			</p>
			<p>
				An illustration:<br />
				- you request a page, the session cookie containing ID-A is sent to the server.<br />
				- your page sends two ajax requests. the session cookie containing ID-A is again sent to the server with each request.<br />
				- ajax request 1 finishes, and rotates the ID. A cookie with ID-B is sent to the browser.<br />
				- now ajax request 2 finishes. Because it sent the same cookie, it also decides to rotate, this time to ID-C.<br />
				(you will get a different ID, because session IDs are generated using a randomized algorithm)<br />
			</p>
			<p>
				Now we have a problem. The session class tries to update the stored session with key ID-A to ID-C, but it can't find that session.
				Remember, it had been updated from ID-A to ID-B by the first ajax call! So it decides the session is invalid, create a new and empty
				session, and return that cookie to the browser. Now your valid cookie is overwritten by the new and empty session cookie.
				Result: you have lost the session.
			</p>
			<p>
				This is an issue that most frameworks have not solved. Enter Fuel!
			</p>
			<p>
				Fuel's session class contains two mechanisms to detect and mitigate this problem.
				Every session key store contains two session IDs: the current ID and the previous ID.
				If a request comes in just after the session id has been rotated, the correct session can be located using the previous session id stored in the key store.
				And it case of a session id mismatch which could not be recovered using the previous id, no updated cookie will be sent back to the browser.
				The result is that you lose the session data of that request, but you don't lose the session itself.
			</p>

			<h3 id="no-cookies">Sessions without cookies</h3>

			<p>
				After a change to the session data, the Session class will always generate a session cookie, and send it to the client in the HTTP
				response header. However, there are situations where is it undesireable, of even impossible, to use cookies. For example simply
				because the client does not support them.
			</p>
			<p>
				In these cases, there are alternative ways to pass a Session ID back to the application on a request from the client:
			</p>

			<ul>
				<li>via a <strong>GET</strong> variable. The name of the variable in the URL must be equal to the name of the cookie defined in the configuration.</li>
				<li>via a <strong>POST</strong> variable. You can define the form field name (post_cookie_name) that contains the session-id in the configuration.</li>
				<li>via the <strong>HTTP header</strong>. When constructing the HTTP request client side, you can add a "Session-Id" HTTP header with the session id.</li>
			</ul>

			<p>
				You can use <code>Session::key()</code> to retrieve the current session id, so you can pass it to the client in the response, instead
				of using a cookie. If you have configured encryption in your session configuration, you need to encrypt the id:
			</p>

			<pre class="php"><code>// fetch the session ID and encrypt it
$session_id = \Crypt::encode(\Session::key());
</code></pre>

		</div>

		<footer>
			<p>
				&copy; FuelPHP Development Team 2010-2013 - <a href="http://fuelphp.com">FuelPHP</a> is released under the MIT license.
			</p>
		</footer>
	</div>
</body>
</html>
